# -*- coding: utf-8 -*-
# @Time     :2021/9/9 10:49
# @Author   : master
# @Software : PyCharm


# 封装基本函数 - 执行日志、异常处理、失败截图
# 所有的页面公共部分
import logging
import win32gui
import win32con
from time import *
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver import ActionChains
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait
import datetime
from Common import dir_config, logger


class BasePage():

    def __init__(self, driver):
        self.driver = driver

    def open(self, url, t='', timeout=10):
        '''
        使用 get 打开 url 后，最大化窗口，刞断 title 符合预期
        '''
        self.driver.get(url)
        self.driver.maximize_window()

        try:
            WebDriverWait(self.driver, timeout,
                          1).until(EC.title_contains(t))

        except TimeoutException:
            print("open %s title error" % url)

        except Exception as msg:
            print("Error:%s" % msg)

    def find_element(self, locator, timeout=10, doc=''):
        '''
        定位元素，参数 locator 是元祖类型
        Usage:
        locator = ("id","xxx")
        driver.find_element(locator)
        '''
        logging.info('查找元素：{}'.format(locator))
        try:
            element = WebDriverWait(
                self.driver, timeout, 1).until(
                EC.presence_of_element_located(locator))
        except BaseException:
            logging.exception('查找元素失败')
            self.save_screenshot(doc)
            raise
        return element

    def find_elements(self, locator, timeout=10):
        '''定位一组元素'''
        elements = WebDriverWait(
            self.driver, timeout, 1).until(
            EC.presence_of_all_elements_located(*locator))
        logging.info('查找元素：{}'.format(locator))
        return elements

    def click(self, locator, doc=""):
        '''
        点击操作
        :param locator:
        :return:
        '''
        try:
            element = self.find_element(locator)
            element.click()
        except BaseException:
            logging.exception("元素点击操作失败！！！")
            self.save_screenshot(doc)
            raise

    def send_keys(self, locator, text, doc=''):
        '''
        发送文本，清空后输入
        Usage:
        locator = ("id","xxx")
        driver.send_keys(locator, text)
        '''
        try:
            element = self.find_element(locator)
            element.clear()
            element.send_keys(text)
        except BaseException:
            logging.exception("元素输入操作失败！！！")
            self.save_screenshot(doc)
            raise

    def is_text_in_element(self, locator, text, timeout=10):
        '''
        判断文本在元素里,没定位到元素返回 False，定位到返回判
        断结果布尔值）
        result = driver.text_in_element(locator, text)
        '''
        try:
            result = WebDriverWait(
                self.driver, timeout, 1).until(
                EC.text_to_be_present_in_element(
                    *locator, text))
            logging.info('{}在元素{}里'.format(text, locator))
        except TimeoutException:
            logging.info('元素{}未定位到'.format(locator))
            return False
        else:
            return result

    def is_text_in_value(self, locator, value, timeout=10):
        '''
        判断元素的 value 值，没定位到元素返回 false,定位到返回判
        断结果布尔值
        result = driver.text_in_element(locator, text)
        '''
        try:
            result = WebDriverWait(
                self.driver, timeout, 1).until(
                EC.text_to_be_present_in_element_value(
                    *locator, value))
        except TimeoutException:
            print("元素没定位刡：" + str(*locator))
            logging.info('元素{}未定位到'.format(locator))
            return False
        else:
            return result

    def is_title(self, title, timeout=10):
        '''判断 title 完全等于'''
        try:
            result = WebDriverWait(self.driver, timeout,
                                   1).until(EC.title_is(title))
            return result
        except BaseException:
            print('title不完全相等')
            logging.info('title不完全相等')

    def is_title_contains(self, title, timeout=10):
        '''判断 title 包含'''
        try:
            result = WebDriverWait(self.driver, timeout,
                                   1).until(EC.title_contains(title))
        except BaseException:
            print('title中不包含{}'.format(title))
            logging.info('title中不包含{}'.format(title))

    def is_selected(self, locator, timeout=10):
        '''判断元素被选中，返回布尔值,'''
        result = WebDriverWait(
            self.driver, timeout, 1).until(
            EC.element_located_to_be_selected(*locator))
        return result

    def is_selected_be(self, locator, selected=True,
                       timeout=10):
        '''判断元素的状态，selected 是期望的参数 true/False
        返回布尔值'''
        result = WebDriverWait(
            self.driver, timeout, 1).until(
            EC.element_located_selection_state_to_be(
                *locator, selected))
        return result

    def is_alert_present(self, timeout=10):
        '''判断页面是否有 alert，
        有返回alert(注意返里是返回 alert,不是 True)
        没有返回 False'''
        result = WebDriverWait(self.driver, timeout,
                               1).until(EC.alert_is_present())
        return result

    def is_invisibility(self, locator, timeout=10, doc=''):
        '''等待元素可见返回本身，不可见返回 True，没找到元素也返回
        True'''
        logging.info("等待元素 {0} 可见".format(locator))
        try:
            WebDriverWait(
                self.driver, timeout, 1).until(
                EC.invisibility_of_element_located(locator))
        except BaseException:
            logging.exception("等待元素可见失败！！！")
            self.save_screenshot(doc)
            raise

    def is_clickable(self, locator, timeout=10):
        '''元素可以点击 is_enabled 返回本身，不可点击返回 Fasle'''
        result = WebDriverWait(self.driver, timeout,
                               1).until(EC.element_to_be_clickable(*locator))
        return result

    def is_located(self, locator, timeout=10):
        '''判断元素有没被定位到（并不意味着可见），定位到返回
        element,没定位到返回 False'''
        result = WebDriverWait(
            self.driver, timeout, 1).until(
            EC.presence_of_element_located(*locator))
        return result

    def move_to_element(self, locator):
        '''
        鼠标悬停操作
        Usage:
        locator = ("id","xxx")
        driver.move_to_element(locator)
        '''
        element = self.find_element(*locator)
        ActionChains(self.driver).move_to_element(element).perform()

    def back(self):
        """
        Back to old window.
        Usage:
        driver.back()
        """
        self.driver.back()

    def forward(self):
        """
        Forward to old window.
        Usage:
        driver.forward()
        """
        self.driver.forward()

    def close(self):
        """
        Close the windows.
        Usage:
        driver.close()
        """
        self.driver.close()

    def quit(self):
        """
        Quit the driver and close all the windows.
        Usage:
        driver.quit()
        """
        self.driver.quit()

    def get_title(self):
        '''获取 title'''
        return self.driver.title

    def get_text(self, locator, doc=''):
        '''获取文本'''
        try:
            element = self.find_element(*locator)
            return element.text
        except BaseException:
            logging.exception('获取元素文本操作失败！！！')
            self.save_screenshot(doc)

    def get_attribute(self, locator, name, doc):
        '''获取元素属性'''
        try:
            element = self.find_element(*locator)
            return element.get_attribute(name)
        except BaseException:
            logging.exception('获取元素属性操作失败！！！')
            self.save_screenshot(doc)

    def js_execute(self, js):
        '''执行 js'''
        return self.driver.execute_script(js)

    def js_focus_element(self, locator):
        '''聚焦元素'''
        target = self.find_element(*locator)
        self.driver.execute_script("arguments[0].scrollIntoView();", target)

    def js_scroll_top(self):
        # '''滚动到顶部'''

        js = "window.scrollTo(0,0)"
        self.driver.execute_script(js)

    def js_scroll_end(self):
        '''滚动到底部'''
        js = "window.scrollTo(0,document.body.scrollHeight)"
        self.driver.execute_script(js)

    def select_by_index(self, locator, index):
        '''通过索引,index 是索引第几个，从 0 开始'''
        element = self.find_element(*locator)
        Select(element).select_by_index(index)

    def select_by_value(self, locator, value):
        '''通过 value 属性'''
        element = self.find_element(*locator)
        Select(element).select_by_value(value)

    def select_by_text(self, locator, text):
        '''通过文本值定位'''
        element = self.find_element(*locator)
        Select(element).select_by_value(text)

    def upload_file(self, file_path):
        # 一级窗口
        dialog = win32gui.FindWindow("#32770", "打开")

        # 二级窗口
        ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, "ComboBoxEx32", None)

        # 三级窗口
        ComboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, "ComboBox", None)

        # 文本的输入窗口 -- 四级窗口
        edit = win32gui.FindWindowEx(ComboBox, 0, "Edit", None)

        # 打开按钮 -- 二级窗口
        button = win32gui.FindWindowEx(dialog, 0, "Button", "打开(&O)")

        # 输入文件地址：
        win32gui.SendMessage(edit, win32con.WM_SETTEXT, None, file_path)
        sleep(2)
        # 点击打开按钮，提交文件
        win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)

    def wait_eleVisible(self, locator, times=30, poll_frequency=0.5, doc=""):
        '''
        等待元素可见
        :param locator:
        :param times:
        :param poll_frequency:
        :param doc:
        :return: 模块名_页面名称_操作名称
        '''
        logging.info("等待元素 {0} 可见".format(locator))
        try:
            # 开始等待时间
            start = datetime.datetime.now()
            WebDriverWait(
                self.driver, times, poll_frequency).until(
                EC.invisibility_of_element_located(locator))
            # 结束等待的时间点
            end = datetime.datetime.now()
            diff = end - start
            logging.info("等待结束，等待时长位：{}".format(diff.total_seconds()))
        except BaseException:
            logging.exception('等待元素可见失败！！！')
            # 截图
            self.save_screenshot(doc)
            raise

    def is_visibility(self, locator, timeout=10, doc=''):
        '''元素可见返回本身，不可见返回 Fasle'''
        try:
            result = WebDriverWait(
                self.driver, timeout, 1).until(
                EC.visibility_of_element_located(locator))
        except BaseException:
            logging.exception('等待元素可见失败!!!')
            self.save_screenshot(doc)
            raise
        return result

    def save_screenshot(self, name):
        '''异常截图'''
        # 图片名称 ： 模块名_页面名称_操作名称_时间.png
        nowTime = datetime.datetime.now()
        file_name = '{0} _ {1}.png'.format(name, nowTime)
        self.driver.save_screenshot("截图存放路径" + file_name)
        logging.info("截取网页成功，文件路径为：{}".format(file_name))
